from sls_mirrors.sls_mqttClient import MQTTClient
from sls_controller.sls_missionsSchedule import MissionsSchedule
from sls_controller.sls_missionsFactory import MissionsFactory
from sls_controller.sls_publicResource import PublicResource
from sls_controller.sls_publicDefine import *
import json
import threading
import time
from sls_controller.sls_entity import EntityUpdate
###add the entity update!!!!!!!!!!!!!!!!!!!!!!!!!!!!
from sls_controller.sls_uavEntityUpdates import *
from sls_controller.sls_ugvEntityUpdates import *
from queue import Queue
from sls_controller.sls_entity import Entity

        
#创建一个单例类，用于使用MqqtClient并带有Mqtt订阅和发布的回调函数
class RemoteService:
    _instance = None
    
    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._initialized = False
        return cls._instance
        
    def __init__(self,mission_schedule:MissionsSchedule,missions_factory:MissionsFactory,public_resource:PublicResource,local_host_mode:bool = False):
        if self._initialized:
            return
        self.message_sendQueue = Queue()
        self.local_host_mode = local_host_mode    
        self.mqtt_client = MQTTClient(self.local_host_mode)
        self.mqtt_client.set_message_handle_callback(self.message_handle_callback)
        self.mqtt_client.set_connect_handle_callback(self.connect_handle_callback)
        self._initialized = True
        self.mission_schedule = mission_schedule
        self.missions_factory = missions_factory
        self.public_resource = public_resource
        self.entity  = Entity(public_resource)
        # as needed 添加entity_update!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        if self.entity.id.startswith('uav'):
            self.entity.add_entity_updates(BasicPositionEntityUpdate,BasicStatusEntityUpdate,CrossStatusEntityUpdate)
        elif self.entity.id.startswith('ugv'):
            self.entity.add_entity_updates(UGVBasicPositionEntityUpdate,CrossStatusEntityUpdate)
        
        if public_resource.vehicle_class == VehicleClass.UAV:
            self.vehicle_class = VehicleClass.UAV
        elif public_resource.vehicle_class == VehicleClass.UGV:
            self.vehicle_class = VehicleClass.UGV

        self.mission_schedule.set_runingTask_changed_callback(self.publish_runingTask_changed)

        ms_pub_id = self.entity.id
        # 任务订阅和发布相关
        self.ms_sub_topics = [
            "/command/"+ms_pub_id+"/MS",
        ]
        self.ms_pub_topics = [
            "/status/"+ms_pub_id+"/MS/runingTask",
            "/status/"+ms_pub_id+"/MS/missionsList",
            "/status/"+ms_pub_id+"/MS/scheduleState",
        ]
        if self.vehicle_class == VehicleClass.UAV:
            # UAV订阅的主题列表
            self.uav_sub_topics = [

            ]

        elif self.vehicle_class == VehicleClass.UGV:
            # UGV订阅和发布的主题列表
            self.ugv_sub_topics = [

            ]

        #连接mqtt服务器
        self.mqtt_client.connect()    
        # 启动定时任务
        self._start_periodic_task()

    #正在执行的任务发布
    def publish_runingTask_changed(self,task_index):
        """发布任务完成消息"""
        datasets = self.mission_schedule.read_mission_data_from_index(task_index)
        name = self.mission_schedule.read_mission_name_from_index(task_index)
        task_data = {
            "missionsType": name,
            "datasets": datasets,
            "missionsIndex": task_index
        }
        self.put_message_to_sendQueue(self.ms_pub_topics[0], task_data)
        #self.mqtt_client.publish_message(self.ms_pub_topics[0], task_data)
        
    def _periodic_task(self):
        """定时执行的任务"""
        interval = 0.5  # 设置精确的0.5秒间隔
        while True:
            try:
                loop_start = time.time()
                if self.mqtt_client.is_connected() != False:
                    for entity_update in self.entity.entity_update_list:
                        self.mqtt_client.publish_message(entity_update.get_pub_topic(), entity_update.get_dict_data())              
                # 计算需要等待的时间以保持精确的0.5秒间隔
                processing_time = time.time() - loop_start
                sleep_time = max(0, interval - processing_time)
                time.sleep(sleep_time)
                
            except Exception as e:
                print(f"{self.__class__.__name__}的定时发布执行出错: {e}")
                time.sleep(interval)  # 出错后等待0.5秒继续


    def _send_queue_task(self):
        while True:
            message = self.message_sendQueue.get()
            self.mqtt_client.publish_message(message[0], message[1])


    def _start_periodic_task(self):
        """启动定时任务线程"""
        threading.Thread(target=self._periodic_task, daemon=True).start()
        threading.Thread(target=self._send_queue_task, daemon=True).start()


    def uav_message_handle(self, client, userdata, message):
        """处理接收到的MQTT消息"""
        try:
            payload = message.payload.decode()
            topic = message.topic
            print(f"收到消息: topic={topic}, payload={payload}")
        except Exception as e:
            print(f"处理消息时发生错误: {e}")

    def ugv_message_handle(self, client, userdata, message):
        """处理接收到的MQTT消息"""
        try:
            payload = message.payload.decode()
            topic = message.topic
            print(f"收到消息: topic={topic}, payload={payload}")
        except Exception as e:
            print(f"处理消息时发生错误: {e}")
    def ms_message_handle(self, client, userdata, message):
        """处理接收到的关于MS的MQTT消息"""
        try:
            payload = message.payload.decode()
            topic = message.topic
            #print(f"收到消息: topic={topic}, payload={payload}")
            if self.mission_schedule:
                # 根据消息内容处理任务
                if topic == self.ms_sub_topics[0]:
                    mission_data_dict = json.loads(payload)
                    if mission_data_dict["method"] == "start":
                        self.mission_schedule.startMissions()
                    elif mission_data_dict["method"] == "stop":
                        self.mission_schedule.stopMissions()
                    elif mission_data_dict["method"] == "suspend":
                        self.mission_schedule.suspendMissions()
                    elif mission_data_dict["method"] == "restart":
                        self.mission_schedule.restartMissions()
                    elif mission_data_dict["method"] == "append_missions":
                        self.mission_schedule.append_missions_from_list(mission_data_dict["missions"])
                    elif mission_data_dict["method"] == "append_mission":
                        self.mission_schedule.append_mission_from_dict(mission_data_dict["mission"])
                    elif mission_data_dict["method"] == "add_mission":
                        self.mission_schedule.add_mission_from_dict(mission_data_dict["mission"],mission_data_dict["index"])
                    elif mission_data_dict["method"] == "moveup_mission":
                        self.mission_schedule.moveup_mission_from_index(mission_data_dict["index"])
                    elif mission_data_dict["method"] == "movedown_mission":
                        self.mission_schedule.movedown_mission_from_index(mission_data_dict["index"])
                    elif mission_data_dict["method"] == "request_missions_list":
                        data = self.mission_schedule.read_missions_detail_as_list()
                        #send name as json
                        #self.publish_message_thread(self.ms_pub_topics[1],data)
                        self.put_message_to_sendQueue(self.ms_pub_topics[1],data)
                    elif mission_data_dict["method"] == "delete_mission":
                        self.mission_schedule.delete_mission_from_index(mission_data_dict["index"])
                    elif mission_data_dict["method"] == "read_schedule_state":
                        self.put_message_to_sendQueue(self.ms_pub_topics[2],self.mission_schedule.read_schedule_stateAndIndex())
                        #self.publish_message_thread(self.ms_pub_topics[2],self.mission_schedule.read_schedule_stateAndIndex())
                    else:
                        print("unknown method")
        except Exception as e:
            print(f"处理消息时发生错误: {e}")

    def message_handle_callback(self, client, userdata, message):
        self.ms_message_handle(client, userdata, message)
        if self.vehicle_class == VehicleClass.UAV:
            self.uav_message_handle(client, userdata, message)
        elif self.vehicle_class == VehicleClass.UGV:
            self.ugv_message_handle(client, userdata, message)

                        
    def publish_status(self, status_data: dict):
        """发布状态信息"""
        try:
            status_json = json.dumps(status_data)
            self.mqtt_client.publish_message("vehicle/status", status_json)
        except Exception as e:
            print(f"发布状态时发生错误: {e}")
    
    def connect_handle_callback(self, client, userdata, flags, rc):
        """连接成功后的回调函数"""
        if rc == 0:
            print("连接成功")
            # 连接成功后根据类型订阅默认主题
            self.mqtt_client.subscribe_topics(self.ms_sub_topics)
            if self.vehicle_class == VehicleClass.UAV:
                self.mqtt_client.subscribe_topics(self.uav_sub_topics)
            elif self.vehicle_class == VehicleClass.UGV:
                self.mqtt_client.subscribe_topics(self.ugv_sub_topics)
        else:
            print("连接失败，返回码:", rc)          
    
    def subscribe_additional_topic(self, topic: str):
        """订阅额外的主题"""
        self.mqtt_client.subscribe_topics([topic])
        
    def unsubscribe_topic(self, topic: str):
        """取消订阅指定主题"""
        self.mqtt_client.unsubscribe_topics([topic])

    #以新的线程调用self.mqtt_client.publish_message发送
    # def publish_message_thread(self, topic: str, data: dict|list):
    #     """以新的线程调用self.mqtt_client.publish_message发送"""
    #     threading.Thread(target=self.mqtt_client.publish_message, args=(topic, data)).start()
    
    def put_message_to_sendQueue(self, topic: str, data: dict|list):
        """将消息放入队列"""
        self.message_sendQueue.put((topic, data))

   
